﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Zj.Blog.Infrastructure.Extension
{
    public static class SqlDataReaderExt
    {
        public static Func<SqlDataReader, T> ToExpression<T>(this SqlDataReader dr)
            where T:class,new()
        {
            if (null == dr || !dr.HasRows || dr.IsClosed)
            {
                throw new Exception("SqlDataReader已经失效");
            }
            var paraExp = Expression.Parameter(typeof(SqlDataReader), "dr");
            List<MemberBinding> bindingList = new List<MemberBinding>();
            //if (reader == null || reader.IsClosed || !reader.HasRows)
            //    throw new ArgumentException("reader", "当前对象无效");
            //ParameterExpression parameter = Expression.Parameter(typeof(SqlDataReader), "reader");
            //List<MemberBinding> binds = new List<MemberBinding>();
            for (int i = 0; i < dr.FieldCount; i++)
            {
                //dr.GetFieldValue<int>(,);

                PropertyInfo prop = typeof(T).GetProperty(dr.GetName(i));
                var mInfo = typeof(SqlDataReader).GetMethod("GetFieldValue").MakeGenericMethod(prop.PropertyType);
                var callExp = Expression.Call(paraExp, mInfo, Expression.Constant(i));
                bindingList.Add(Expression.Bind(prop, callExp));

                //String colName = reader.GetName(i);
                //PropertyInfo pInfo = typeof(T).GetProperty(colName);
                //if (pInfo == null || !pInfo.CanWrite) continue;
                //MethodInfo mInfo = reader.GetType().GetMethod("GetFieldValue").MakeGenericMethod(pInfo.PropertyType);
                //MethodCallExpression call = Expression.Call(parameter, mInfo, Expression.Constant(i));
                //MemberAssignment bind = Expression.Bind(pInfo, call);
                //binds.Add(bind);
            }
            //MemberInitExpression init = Expression.MemberInit(Expression.New(typeof(T)), binds.ToArray());
            //return Expression.Lambda<Func<SqlDataReader, T>>(init, parameter).Compile();
            var init = Expression.MemberInit(Expression.New(typeof(T)), bindingList);
            return Expression.Lambda<Func<SqlDataReader, T>>(init, paraExp).Compile();


        }
    }
}
